using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace Konst3d.Efficiency
{
    public class ObservableIdentifiableCollection<TItem, TId>: IIdentifiableCollection<TItem, TId> where TItem : IIdentifiable<TId>
    {
        #region Types

        public delegate void ItemCallback(TItem item);

        #endregion // Types

        #region Events

        public event ItemCallback ItemAdded;
        public event ItemCallback ItemRemoved;

        #endregion // Events

        #region IIdentifiableCollection<TItem, TId> Members

        public int Count
        {
            get
            {
                return _items.Count;
            }
        }

        public TItem this[TId id]
        {
            get
            {
                Contract.Requires(Contains(id));

                return _items[id];
            }
        }

        public IEnumerator<TItem> GetEnumerator()
        {
            return _items.Values.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _items.Values.GetEnumerator();
        }

        public bool Contains(TId id)
        {
            return _items.ContainsKey(id);
        }

        public void Add(TItem item)
        {
            Contract.Requires(!Contains(item.ID));

            _items.Add(item.ID, item);

            if (ItemAdded != null)
            {
                ItemAdded(item);
            }
        }

        public void Remove(TId id)
        {
            Contract.Requires(Contains(id));

            var item = _items[id];
            _items.Remove(id);

            if (ItemRemoved != null)
            {
                ItemRemoved(item);
            }
        }

        public void Clear()
        {
            if (ItemRemoved != null)
            {
                foreach (var item in _items.Values)
                {
                    _items.Remove(item.ID);
                    ItemRemoved(item);
                }
            }
            else
            {
                _items.Clear();
            }
        }

        #endregion

        #region Fields

        private Dictionary<TId, TItem> _items = new Dictionary<TId, TItem>();

        #endregion // Fields
    }
}
